#include "AppGlobal.h"

static bool gIsScannerPay = false;
static u8 gQrCodeType = 0;
static s8 *gPayment = NULL;
static TransEntity *gTransEntity = NULL;

static void getQrcodeTradeType(u8 payChannel, s8 *tradeType)
{
    switch (payChannel)
    {
        case QRCODE_MODE_WECHAT:
            strcpy(tradeType, "41");
            break;

        case QRCODE_MODE_ALI:
        case QRCODE_MODE_ANT:
            strcpy(tradeType, "42");
            break;

        case QRCODE_MODE_UNION:
            strcpy(tradeType, "46");
            break;

        default:
            break;
    }
}

static u32 formField47Data(u8 *field47, s8 *order)
{
    s8 iccid[32] = {0};
    s8 locationInfo[36 + 1] = {0};
    u32 field47Len = ZERO;

    libGetIccID(iccid, sizeof(iccid));
    getLocationInfo(locationInfo, sizeof(locationInfo));

    field47Len = formTlvData(field47, (u32) field47Len, "0001", (u8 *) iccid, strlen(iccid));
    field47Len = formTlvData(field47, (u32) field47Len, "0002", (u8 *) "T1", 2);
    if (strlen(locationInfo) != 0)
    {
        field47Len = formTlvData(field47, field47Len, "0004", (u8 *) locationInfo, strlen(locationInfo));
    }

    if (order != NULL && strlen(order) != 0)
    {
        field47Len = formTlvData(field47, field47Len, "3302", (u8 *) order, strlen(order));
    }

    return field47Len;
}

static s32 formQrCodeQueryBag(SDK_8583_ST8583 *pstBag8583)
{
    u8 field47[128] = {0};
    u32 field47Len = 0;
    s8 tradeType[2 + 1] = {0};
    u8 field60[16] = {0};
    s8 tusn[32] = {0};
    s8 transTime[14 + 1] = {0};

    if (pstBag8583 == NULL || lib8583BuildPublicField(pstBag8583, "3200000000C20011") <= 0)
    {
        return 0;
    }

    field47Len = formField47Data(field47, gTransEntity->mTransDetails.mOrder);
    libGetPosStrTime(transTime, sizeof(transTime));
    sdkSecurityRequestDeviceSn(tusn, sizeof(tusn));
    if (gQrCodeType == 0) gQrCodeType = gTransEntity->mTransDetails.mQrCodeMode;
    getQrcodeTradeType(gQrCodeType, tradeType);
    snprintf((s8 *) field60, sizeof(field60), "%s%s", tradeType, VALUE_PROP_BATCH_NO);

    sdk8583SetField(pstBag8583, SDK_8583_FIELD_MSG, (u8 *) "0200", 4);
    sdk8583SetField(pstBag8583, 3, (u8 *) "320000", 6);
    sdk8583SetField(pstBag8583, 7, (u8 *) transTime, (u16) strlen(transTime));
    sdk8583SetField(pstBag8583, 11, (u8 *) gTransEntity->mTransDetails.mOrder, (u16) strlen(gTransEntity->mTransDetails.mOrder));
    sdk8583SetField(pstBag8583, 25, (u8 *) (gIsScannerPay ? "10" : "20"), 2);
    sdk8583SetField(pstBag8583, 41, (u8 *) tusn, (u16) strlen(tusn));
    sdk8583SetField(pstBag8583, 47, field47, (u16) field47Len);
    sdk8583SetField(pstBag8583, 60, field60, (u16) strlen((s8 *) field60));

    return pstBag8583->nBagLen;
}

static s32 formQrcodePayBag(SDK_8583_ST8583 *pstBag8583)
{
    u8 field47[256] = {0};
    u32 field47Len = 0;
    s8 tradeType[2 + 1] = {0};
    s8 tusn[32] = {0};
    u8 field60[16] = {0};
    s8 transTime[14 + 1] = {0};
    s8 order[32] = {0};
    TransQrCodeCache *qrCodeCache = NULL;

    if (pstBag8583 == NULL || lib8583BuildPublicField(pstBag8583, "3200008004C00011") <= 0)
    {
        return 0;
    }

    sdkSecurityRequestDeviceSn(tusn, sizeof(tusn));

    libGetPosStrTime(transTime, sizeof(transTime));

    snprintf(order, sizeof(order), "%s%s%s", tusn + 8, transTime + 8, VALUE_PROP_VOUCHER_NO);

    qrCodeCache = libTransGetQrCodeCache();
    snprintf(qrCodeCache->mTransInput->mOrder, sizeof(qrCodeCache->mTransInput->mOrder), "%s", order);

    libIncVoucherNo(1);
    field47Len = formField47Data(field47, NULL);

    getQrcodeTradeType(gQrCodeType, tradeType);
    snprintf((s8 *) field60, sizeof(field60), "%s%s", tradeType, VALUE_PROP_BATCH_NO);

    sdk8583SetField(pstBag8583, SDK_8583_FIELD_MSG, (u8 *) "0200", 4);
    sdk8583SetField(pstBag8583, 3, (u8 *) "910000", 6);
    sdk8583SetField(pstBag8583, 7, (u8 *) transTime, (u16) strlen(transTime));
    sdk8583SetField(pstBag8583, 11, (u8 *) order, (u16) strlen(order));
    sdk8583SetField(pstBag8583, 25, (u8 *) (gIsScannerPay ? "10" : "20"), 2);
    sdk8583SetField(pstBag8583, 38, (u8 *) "000000", 6);
    sdk8583SetField(pstBag8583, 41, (u8 *) tusn, (u16) strlen(tusn));
    if (gIsScannerPay)
    {
        sdk8583SetField(pstBag8583, 46, (u8 *) gPayment, (u16) strlen(gPayment));
    }
    sdk8583SetField(pstBag8583, 47, field47, (u16) field47Len);
    sdk8583SetField(pstBag8583, 60, field60, (u16) strlen((s8 *) field60));

    return pstBag8583->nBagLen;
}

static void updateCommuSendParam(bool disconnect, bool hideDisp, s8 *ascIp, s8 *ascPort, TransmitAddress *address, TransmitAttr *attr)
{
    if (ascIp != NULL && strlen(ascIp) != 0 && address)
    {
        snprintf(address->mAsciiIP, sizeof(address->mAsciiIP), "%s", ascIp);
    }
    if (ascPort != NULL && strlen(ascPort) != 0 && address)
    {
        snprintf(address->mAsciiPort, sizeof(address->mAsciiPort), "%s", ascPort);
    }

    if (attr)
    {
        attr->mKeepLink = (bool) !disconnect;
        attr->mHideTransmitView = hideDisp;
        if (attr->mHideTransmitView)
        {
            attr->mEnableCancelWhenRecvData = true;
        }
    }
}

s32 transmitQrcodeScanner(Transmit8583Data *transmitData, s8 *payInfo, s8 *amount)
{
    TransQrCodeCache *qrCodeCache = NULL;
    TransmitAddress transmitAddress = {0};
    TransmitAttr transmitAttr = {0};
    s32 ret = 0;

    gIsScannerPay = true;
    gPayment = payInfo;

    gQrCodeType = libTransGetQrCodeType(payInfo);

    qrCodeCache = libTransGetQrCodeCache();
    snprintf(qrCodeCache->mTransInput->mAmount, sizeof(qrCodeCache->mTransInput->mAmount), "%s", amount);
    qrCodeCache->mQrcodeMode = (QRCODE_MODE) gQrCodeType;

    openReplaceDynamicFields();
    lib8583InitBag(&transmitData->mSendBag);
    lib8583InitBag(&transmitData->mRecvBag);

    updateCommuSendParam(true, false, QRCODE_SERVER_IP, QRCODE_SERVER_PORT, &transmitAddress, NULL);
    transmitData->mTransType = qrCodeCache->mTransInput->mTransType;
    libTransmitBuildAttr(&transmitAttr, false, false, SOCKET_TYPE_TCP, "");
    ret = lib8583TransmitById(NULL, &transmitAddress, &transmitAttr, transmitData, formQrcodePayBag, TRANSMIT_MODE_8583_REVERSAL);

    closeReplaceDynamicFields();
    return ret;
}

s32 transmitQrcodeCreate(Transmit8583Data *transmitData, u8 qrCodeType, s8 *amount)
{
    TransQrCodeCache *qrCodeCache = NULL;
    TransmitAddress transmitAddress = {0};
    s32 ret = 0;

    gIsScannerPay = false;
    gQrCodeType = qrCodeType;

    qrCodeCache = libTransGetQrCodeCache();
    snprintf(qrCodeCache->mTransInput->mAmount, sizeof(qrCodeCache->mTransInput->mAmount), "%s", amount);
    qrCodeCache->mQrcodeMode = (QRCODE_MODE) gQrCodeType;

    openReplaceDynamicFields();
    lib8583InitBag(&transmitData->mSendBag);
    lib8583InitBag(&transmitData->mRecvBag);

    updateCommuSendParam(true, false, QRCODE_SERVER_IP, QRCODE_SERVER_PORT, &transmitAddress, NULL);
    transmitData->mTransType = qrCodeCache->mTransInput->mTransType;
    ret = lib8583TransmitById(NULL, &transmitAddress, NULL, transmitData, formQrcodePayBag, TRANSMIT_MODE_8583_RECORD);

    closeReplaceDynamicFields();
    return ret;
}

s32 transmitQrcodeScannerQuery(TransEntity *transEntity, Transmit8583Data *transmitData, bool hideTransView)
{
    TransmitAddress transmitAddress = {0};
    TransmitAttr transmitAttr = {0};
    s32 ret = 0;

    gTransEntity = transEntity;

    openReplaceDynamicFields();
    lib8583InitBag(&transmitData->mSendBag);
    lib8583InitBag(&transmitData->mRecvBag);

    transmitData->mTransType = TRANS_TYPE_SCAN_QUERY;
    updateCommuSendParam(true, hideTransView, QRCODE_SERVER_IP, QRCODE_SERVER_PORT, &transmitAddress, &transmitAttr);
    ret = lib8583Transmit(&transmitAddress, &transmitAttr, transmitData, formQrCodeQueryBag);

    closeReplaceDynamicFields();
    return ret;
}

s32 transmitQrcodeCreateQuery(TransEntity *transEntity, Transmit8583Data *transmitData, bool hideTransView)
{
    TransmitAddress transmitAddress = {0};
    TransmitAttr transmitAttr = {0};
    s32 ret = 0;

    gTransEntity = transEntity;

    openReplaceDynamicFields();
    lib8583InitBag(&transmitData->mSendBag);
    lib8583InitBag(&transmitData->mRecvBag);

    transmitData->mTransType = TRANS_TYPE_QRCODE_QUERY;
    updateCommuSendParam(true, hideTransView, QRCODE_SERVER_IP, QRCODE_SERVER_PORT, &transmitAddress, &transmitAttr);

    ret = lib8583Transmit(&transmitAddress, &transmitAttr, transmitData, formQrCodeQueryBag);

    closeReplaceDynamicFields();
    return ret;
}

void initQrCode()
{
    gIsScannerPay = false;
    gQrCodeType = 0;
    gPayment = NULL;
    gTransEntity = NULL;

    platform_qrcode_set_transmit_qrcode_scanner_func((TransmitQrcodeScannerFunc) transmitQrcodeScanner);
    platform_qrcode_set_transmit_qrcode_create_func((TransmitQrcodeCreateFunc) transmitQrcodeCreate);
    platform_qrcode_set_transmit_qrcode_scanner_query_func((TransmitQrcodeScannerQueryFunc) transmitQrcodeScannerQuery);
    platform_qrcode_set_transmit_qrcode_create_query_func((TransmitQrcodeCreateQueryFunc) transmitQrcodeCreateQuery);
    platform_qrcode_set_update_record_func((UpdateQrCodeTransEntityByRecvData) updateTransEntityByRecvData);
}